package com.ruoyi.cyx;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author: 程昱轩
 * @Description: TODO
 * @DateTime: @date 2023/3/22 20:10
 **/

public class AverageCapitalPlusInterestUtils {
    /**
     * 每月偿还本金和利息
     * <p>
     * 公式：每月偿还本息=〔贷款本金×月利率×(1＋月利率)＾还款月数〕÷〔(1＋月利率)＾还款月数-1〕
     *
     * @param invest     总借款额（贷款本金,单位分）
     * @param yearRate   年利率
     * @param totalMonth 还款总月数
     * @return 每月偿还本金和利息(入1 单位分)
     */
    public static double getPerMonthPrincipalInterest(double invest, double yearRate, int totalMonth) {
        double monthRate = yearRate / 12;
        double perMonthPrincipalInterest = invest * (monthRate * Math.pow(1 + monthRate, totalMonth))/(Math.pow(1 + monthRate, totalMonth) - 1);
        return new BigDecimal(perMonthPrincipalInterest).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    /**
     * 等额本息的每月偿还利息
     * <p>
     * 公式：每月偿还利息=贷款本金×月利率×〔(1+月利率)^还款月数-(1+月利率)^(还款月序号-1)〕÷〔(1+月利率)^还款月数-1〕
     *
     * @param invest     总借款额（贷款本金,分）
     * @param yearRate   年利率
     * @param totalMonth 还款总月数
     * @return 每月偿还利息(入1 单位分)
     */
    public static Map<Integer, Double> getPerMonthInterest(double invest, double yearRate, int totalMonth) {
        Map<Integer, Double> map = new HashMap<>();
        double monthRate = yearRate / 12;
        double monthInterest;
        for (int i = 1; i < totalMonth + 1; i++) {
            double multiply = invest * monthRate;
            double sub = Math.pow(1 + monthRate, totalMonth) - Math.pow(1 + monthRate, i - 1);
            monthInterest = multiply * sub/(Math.pow(1 + monthRate, totalMonth) - 1);
            map.put(i, new BigDecimal(monthInterest).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
        }
        return map;
    }

    /**
     * 等额本息的每月偿还本金（月还本息-月还利息）
     *
     * @param invest     总借款额（贷款本金,分）
     * @param yearRate   年利率
     * @param totalMonth 还款总月数
     * @return 每月偿还本金(取整舍 单位分)
     */
    public static Map<Integer, Double> getPerMonthPrincipal(double invest, double yearRate, int totalMonth) {
        double monthRate = yearRate / 12;
        double monthIncome = invest * monthRate * Math.pow(1 + monthRate, totalMonth)
                /(Math.pow(1 + monthRate, totalMonth) - 1);
        double perMonthPrincipalInterest = new BigDecimal(monthIncome).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();

        Map<Integer, Double> mapPrincipal = new HashMap<>();
        double monthInterest;
        for (int i = 1; i < totalMonth + 1; i++) {
            Double multiply = invest * monthRate;
            double sub = (Math.pow(1 + monthRate, totalMonth)) - (Math.pow(1 + monthRate, i - 1));
            monthInterest = multiply* sub/(Math.pow(1 + monthRate, totalMonth) - 1);
            double monthInterestL = new BigDecimal(monthInterest).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
            // System.out.println("===perMonthPrincipalInterest===="+perMonthPrincipalInterest);
            // System.out.println("===monthInterestL===="+monthInterestL);
            // System.out.println("===perMonthPrincipalInterest-monthInterestL===="+(perMonthPrincipalInterest-monthInterestL));
            // System.out.println("===perMonthPrincipalInterest-monthInterestL===="+ new BigDecimal(perMonthPrincipalInterest).subtract(new BigDecimal(monthInterestL)).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
            // mapPrincipal.put(i, perMonthPrincipalInterest-monthInterestL);
            mapPrincipal.put(i, new BigDecimal(perMonthPrincipalInterest).subtract(new BigDecimal(monthInterestL)).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
        }
        return mapPrincipal;
    }

    /**
     * 等额本息的总利息
     *
     * @param invest     总借款额（贷款本金）
     * @param yearRate   年利率
     * @param totalMonth 还款总月数
     * @return 总利息 (单位分)
     */
    public static double getInterestCount(double invest, double yearRate, int totalMonth) {
        double count = 0;
        Map<Integer, Double> mapInterest = getPerMonthInterest(invest, yearRate, totalMonth);

        for (Map.Entry<Integer, Double> entry : mapInterest.entrySet()) {
            count = new BigDecimal(count).add(new BigDecimal(entry.getValue())).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
        }
        return count;
    }




}
